import cv2
import numpy as np
from PyQt6.QtCore import QTimer
from PyQt6.QtGui import QImage, QPixmap

from database_manager import db_manager


class FaceController:
    def __init__(self, view):
        self.view = view
        self.cap = None
        self.timer = None
        self.face_templates = {}  # 存储人脸模板数据
        self.face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
        self.load_face_templates()  # 加载数据库中的人脸模板

    def on_face_clicked(self):
        """处理人脸识别按钮点击事件：开启摄像头并进行简单识别占位"""
        # 使用UI状态管理器切换到识别模式
        if hasattr(self.view, 'ui_manager'):
            self.view.ui_manager.show_recognition_mode()
        
        self.view.update_display("执行人脸识别操作...")

        # 开启摄像头
        if self.cap is None:
            self.cap = cv2.VideoCapture(0)
        if not self.cap.isOpened():
            self.view.update_display("无法打开摄像头")
            return
        if self.timer is None:
            self.timer = QTimer()
            self.timer.timeout.connect(self._update_frame)
        self.timer.start(30)

    def _update_frame(self):
        if self.cap is None:
            return
        ret, frame = self.cap.read()
        if not ret:
            return
        frame = cv2.flip(frame, 1)

        # 检测人脸并进行模板匹配识别
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = self.face_cascade.detectMultiScale(gray, 1.1, 5)
        
        recognized_name = None
        for (x, y, w, h) in faces:
            # 提取人脸区域
            face_roi = gray[y:y + h, x:x + w]
            
            # 使用模板匹配识别
            recognized_name = self._match_face_template(face_roi)
            
            # 根据识别结果绘制不同颜色的矩形
            if recognized_name:
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)  # 绿色：识别成功
                cv2.putText(frame, recognized_name, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
            else:
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)  # 红色：未识别
                cv2.putText(frame, "Unknown", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            break
        
        # 设置识别到的姓名
        self.view.recognized_name = recognized_name

        rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        h, w, ch = rgb.shape
        bytes_per_line = ch * w
        qimg = QImage(rgb.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)
        if hasattr(self.view, 'video_label'):
            self.view.video_label.setPixmap(QPixmap.fromImage(qimg))

    def stop(self):
        try:
            if self.timer is not None:
                self.timer.stop()
        except Exception:
            pass
        try:
            if self.cap is not None:
                self.cap.release()
        except Exception:
            pass
        self.cap = None

    def load_face_templates(self):
        """从数据库加载人脸模板数据"""
        try:
            rows = db_manager.get_all_faces()
            
            self.face_templates = {}
            for name, face_data_bytes in rows:
                # 将字节数据解码为图像
                nparr = np.frombuffer(face_data_bytes, np.uint8)
                face_img = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)
                if face_img is not None:
                    self.face_templates[name] = face_img
        except Exception as e:
            print(f"加载人脸模板失败: {e}")
            self.face_templates = {}

    def _match_face_template(self, face_roi):
        """使用模板匹配识别人脸"""
        if not self.face_templates:
            return None
        
        best_match_name = None
        best_match_score = 0.0
        match_threshold = 0.75  # 匹配阈值
        
        # 调整人脸区域大小以匹配模板
        face_roi_resized = cv2.resize(face_roi, (100, 100))
        
        for name, template in self.face_templates.items():
            # 调整模板大小以匹配当前人脸
            template_resized = cv2.resize(template, (100, 100))
            
            # 使用模板匹配
            result = cv2.matchTemplate(face_roi_resized, template_resized, cv2.TM_CCOEFF_NORMED)
            _, max_val, _, _ = cv2.minMaxLoc(result)
            
            if max_val > best_match_score and max_val > match_threshold:
                best_match_score = max_val
                best_match_name = name
        
        return best_match_name

    def refresh_templates(self):
        """刷新人脸模板数据（当有新的人脸数据保存时调用）"""
        self.load_face_templates()